package com.lktx.sso.service;

import cn.hserver.core.ioc.annotation.Autowired;
import cn.hserver.core.ioc.annotation.Bean;
import cn.hserver.core.ioc.annotation.Value;
import cn.hutool.crypto.asymmetric.RSA;
import com.lktx.sso.admin.entity.SsoApp;
import com.lktx.sso.admin.entity.SsoAppOidcConfig;
import com.lktx.sso.admin.mapper.SsoAppMapper;
import com.lktx.sso.admin.mapper.SsoAppOidcConfigMapper;

import java.security.interfaces.RSAPublicKey;
import java.util.*;

@Bean
public class OpenIdConfigurationService {

    @Value("oauth.baseIss")
    private String baseIss;

    @Autowired
    private SsoAppOidcConfigMapper ssoAppOidcConfigMapper;

    @Autowired
    private SsoAppMapper ssoAppMapper;


    public Map<String, Object>  jws(String appId) {
        SsoAppOidcConfig ssoAppOidcConfig = ssoAppOidcConfigMapper.selectOneById(appId);
        if (ssoAppOidcConfig == null) {
            return new HashMap<>();
        }
        SsoApp ssoApp = ssoAppMapper.selectOneById(appId);
        List<Map<String, Object>> data = new ArrayList<>();
        Map<String, Object> map = new HashMap<>();
        switch (ssoAppOidcConfig.getIdTokenSignatureAlgorithm()) {
            case "RS256":
                map.put("alg", "RS256");
                map.put("kty","RSA");
                break;
                case "ES256":
                    map.put("alg", "ES256");
                    map.put("kty","ECDSA");
                break;
        }
        map.put("kid", ssoApp.getClientId());
        map.put("use", "sig");

        RSA rsa = new RSA(null,  ssoAppOidcConfig.getPublicKey());
        RSAPublicKey rsaPublicKey = (RSAPublicKey)rsa.getPublicKey();
        byte[] modulus = rsaPublicKey.getModulus().toByteArray();
        byte[] exponent = rsaPublicKey.getPublicExponent().toByteArray();
        // 使用Base64Url编码
        String encodedModulus = base64UrlEncode(modulus);
        String encodedExponent = base64UrlEncode(exponent);
        map.put("n", encodedModulus);
        map.put("e", encodedExponent);
        data.add(map);
        Map<String, Object> map1 = new HashMap<>();
        map1.put("keys", data);
        return map1;
    }

    private  String base64UrlEncode(byte[] input) {
        return Base64.getUrlEncoder().withoutPadding().encodeToString(input);
    }


    public Map<String, Object> getOpenidConfiguration(String appId) {
        SsoAppOidcConfig ssoAppOidcConfig = ssoAppOidcConfigMapper.selectOneById(appId);
        if (ssoAppOidcConfig == null) {
            return new HashMap<>();
        }
        Map<String, Object> map = new HashMap<>();
        map.put("issuer",  String.format("%s/%s", baseIss, appId));
        map.put("authorization_endpoint", String.format("%s/%s/oauth2/authorize", baseIss, appId));
        map.put("token_endpoint", String.format("%s/%s/oauth2/token", baseIss, appId));
        if (ssoAppOidcConfig.getGrantScopes().contains("userinfo")) {
            map.put("userinfo_endpoint", String.format("%s/%s/oauth2/userinfo", baseIss, appId));
        }
        map.put("jwks_uri", String.format("%s/%s/.well-known/jwks.json", baseIss, appId));
        map.put("revocation_endpoint", String.format("%s/%s/oauth2/revoke", baseIss, appId));
        map.put("token_endpoint_auth_methods_supported", List.of("client_secret_basic",
                "client_secret_post",
                "client_secret_jwt",
                "private_key_jwt"));
        map.put("revocation_endpoint_auth_methods_supported", List.of("client_secret_basic",
                "client_secret_post",
                "client_secret_jwt",
                "private_key_jwt"));
        map.put("response_types_supported", List.of("code", "token", "id_token"));
        map.put("grant_types_supported", ssoAppOidcConfig.getGrantScopes());
        //可选参数
        map.put("id_token_signing_alg_values_supported", ssoAppOidcConfig.getIdTokenSignatureAlgorithm());
        map.put("subject_types_supported", List.of("public"));
        Set<String> grantScopes = ssoAppOidcConfig.getGrantScopes();
        grantScopes.add("oidc");
        map.put("scopes_supported",grantScopes);
        return map;
    }
}
